package com.yvon.maple.cloud.web.filter;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.yvon.boot.common.result.ResponseData;
import com.yvon.boot.common.result.ResultCode;
import com.yvon.maple.cloud.web.handler.HttpHandler;
import com.yvon.maple.cloud.web.properties.FeignInsideProperties;
import com.yvon.maple.constants.SystemConstant;
import com.yvon.maple.utils.IpHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.GenericFilterBean;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * @author Yvon
 * @since 2023/1/5
 */
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
@RequiredArgsConstructor
public class FeignInsideFilter extends GenericFilterBean {

    @Resource
    private FeignInsideProperties feignInsideProperties;

    @Resource
    private HttpHandler httpHandler;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        if (!feignRequestCheck(req)) {
            httpHandler.printServerResponseToWeb(ResponseData.failed(ResultCode.UNAUTHORIZED));
            return;
        }
        filterChain.doFilter(req, resp);
    }

    private boolean feignRequestCheck(HttpServletRequest req) {
        // 不是feign请求，不用校验
        if (!req.getRequestURI().startsWith(SystemConstant.Common.FEIGN_INSIDE_URL_PREFIX)) {
            return true;
        }
        // ip白名单
        List<String> ips = feignInsideProperties.getIps();
        // 移除无用的空ip
        ips.removeIf(StrUtil::isBlank);
        // 有ip白名单，ip在白名单内，校验通过
        if (CollectionUtil.isNotEmpty(ips)
                && ips.contains(IpHelper.getIpAddr())) {
            return true;
        }
        String feignInsideSecret = req.getHeader(feignInsideProperties.getKey());
        // 校验feign 请求携带的key 和 value是否正确
        return !StrUtil.isBlank(feignInsideSecret) && Objects.equals(feignInsideSecret, feignInsideProperties.getSecret());
    }
}
